package ${sourceBasePackage}.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DateUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import ${sourceBasePackage}.domain.${entityName};
import ${sourceBasePackage}.dto.${entityName}Dto;
import ${sourceBasePackage}.dto.${entityName}ReqDto;
import ${sourceBasePackage}.repository.${entityName}Repository;
import ${sourceBasePackage}.service.${entityName}Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ${description}(${entityName})业务逻辑实现类
 * @author ${author}
 */
@Service
public class ${entityName}ServiceImpl implements ${entityName}Service {

	@Autowired
	private ${entityName}Repository repository;

    @Override
	public Page<${entityName}Dto> queryPage(${entityName}ReqDto ${entityName?uncap_first}ReqDto) {

        Specification<${entityName}> condition = getCondition(${entityName?uncap_first}ReqDto);
    <#if sortFields?? && (sortFields?size > 0)>
        List<Sort.Order> orderList = new ArrayList<>();
    <#list sortFields as po>
        orderList.add(new Sort.Order(Sort.Direction.${po.listSort?upper_case}, "${po.propertyName}"));
    </#list>
        Sort sort = Sort.by(orderList);
        Pageable pageable = PageRequest.of(${entityName?uncap_first}ReqDto.getPageNoSub1(), ${entityName?uncap_first}ReqDto.getPageSize(), sort);
    <#else>
        Pageable pageable = PageRequest.of(${entityName?uncap_first}ReqDto.getPageNoSub1(), ${entityName?uncap_first}ReqDto.getPageSize());
    </#if>

        Page<${entityName}> page = repository.findAll(condition, pageable);
        List<${entityName}Dto> list = page.getContent().stream().map(item -> {
            ${entityName}Dto ${entityName?uncap_first}Dto = BeanUtil.toBean(item, ${entityName}Dto.class);
            return ${entityName?uncap_first}Dto;
        }).collect(Collectors.toList());

        return new PageImpl<>(list, pageable, page.getTotalElements());
	}

    @Override
	public List<${entityName}Dto> queryList(${entityName}ReqDto ${entityName?uncap_first}ReqDto) {

        Specification<${entityName}> condition = getCondition(${entityName?uncap_first}ReqDto);

        List<${entityName}> list = repository.findAll(condition);
        List<${entityName}Dto> dtoList = list.stream().map(item -> {
            ${entityName}Dto ${entityName?uncap_first}Dto = BeanUtil.toBean(item, ${entityName}Dto.class);
            return ${entityName?uncap_first}Dto;
        }).collect(Collectors.toList());

        return dtoList;
	}

    private Specification<${entityName}> getCondition(${entityName}ReqDto ${entityName?uncap_first}ReqDto) {

        Specification<${entityName}> condition = (root, query, builder) -> {

            List<Predicate> predicateList = new ArrayList<>();

    <#list searchFields as po>
        <#if po.listQuery == 'interval'>
            if(ObjectUtils.isNotEmpty(${entityName?uncap_first}Req.get${po.propertyName?cap_first}Start())) {
                predicateList.add(builder.ge(root.get("${po.propertyName}", ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}Start()));
            }
            if(ObjectUtils.isNotEmpty(${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}End())) {
            <#if po.propertyType == 'Date'>
                ${entityName?uncap_first}ReqDto.set${po.propertyName?cap_first}End(DateUtil.endOfDay(${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}End()));
            </#if>
                predicateList.add(builder.le(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}End()));
            }
        <#else>
            if(ObjectUtils.isNotEmpty(${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}())) {
            <#if po.listQuery == 'like'>
                predicateList.add(builder.like(root.get("${po.propertyName}"), "%" + ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}() + "%"));
            <#elseif po.listQuery == '<'>
                predicateList.add(builder.lt(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            <#elseif po.listQuery == '<='>
                predicateList.add(builder.le(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            <#elseif po.listQuery == '>'>
                predicateList.add(builder.gt(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            <#elseif po.listQuery == '>='>
                predicateList.add(builder.ge(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            <#elseif po.listQuery == '!='>
                predicateList.add(builder.notEqual(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            <#else>
                predicateList.add(builder.equal(root.get("${po.propertyName}"), ${entityName?uncap_first}ReqDto.get${po.propertyName?cap_first}()));
            </#if>
            }
        </#if>
    </#list>

            return builder.and(predicateList.toArray(new Predicate[predicateList.size()]));
        };

        return condition;
    }

    @Override
    public ${entityName}Dto getById(${pkPropertyType} ${pkPropertyName}) {
        ${entityName} ${entityName?uncap_first} = repository.getOne(${pkPropertyName});
        return BeanUtil.toBean(${entityName?uncap_first}, ${entityName}Dto.class);
    }

    @Override
    public void add(${entityName}Dto ${entityName?uncap_first}Dto) {
        ${entityName} ${entityName?uncap_first} = BeanUtil.toBean(${entityName?uncap_first}Dto, ${entityName}.class);
        // TODO

        repository.save(${entityName?uncap_first});
    }

    @Override
    public void update(${entityName}Dto ${entityName?uncap_first}Dto) {
        ${entityName} ${entityName?uncap_first} = repository.getOne(${entityName?uncap_first}Dto.get${pkPropertyName?cap_first}());
        if(${entityName?uncap_first} == null) {
            throw new RuntimeException("数据不存在");
        }
        BeanUtil.copyProperties(${entityName?uncap_first}Dto, ${entityName?uncap_first}, CopyOptions.create().setIgnoreNullValue(true));
        // TODO

        repository.save(${entityName?uncap_first});
    }

    @Override
    public void delete(${pkPropertyType} ${pkPropertyName}) {
        ${entityName} ${entityName?uncap_first} = repository.getOne(${pkPropertyName});
        if(${entityName?uncap_first} == null) {
            throw new RuntimeException("数据不存在");
        }
        repository.deleteById(${pkPropertyName});
    }

}
